package com.wusiwei.service.impl;

import com.wusiwei.common.BusinessException;
import com.wusiwei.entity.Order;
import com.wusiwei.entity.Receipt;
import com.wusiwei.entity.ReceiptItem;
import com.wusiwei.mapper.OrderItemMapper;
import com.wusiwei.mapper.OrderMapper;
import com.wusiwei.mapper.ReceiptItemMapper;
import com.wusiwei.mapper.ReceiptMapper;
import com.wusiwei.service.ReceiptService;
import com.wusiwei.vo.ReceiptStatistics;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 收货单服务实现类
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ReceiptServiceImpl implements ReceiptService {

    private final ReceiptMapper receiptMapper;
    private final OrderMapper orderMapper;
    private final OrderItemMapper orderItemMapper;
    private final ReceiptItemMapper receiptItemMapper;

    @Override
    public List<Receipt> getAllReceipts() {
        log.info("获取所有收货单");
        try {
            // 获取所有收货单基本信息
            List<Receipt> receipts = receiptMapper.getAllReceipts();

            // 为每个收货单加载明细数据
            if (receipts != null && !receipts.isEmpty()) {
                for (Receipt receipt : receipts) {
                    List<ReceiptItem> items = receiptItemMapper.findByReceiptId(receipt.getId());
                    receipt.setItems(items);
                }
                log.info("获取到收货单: {}个, 已加载明细数据", receipts.size());
            }

            return receipts;
        } catch (Exception e) {
            log.error("获取所有收货单失败", e);
            return List.of();
        }
    }

    @Override
    public Receipt getReceiptById(Long id) {
        log.info("根据ID获取收货单: {}", id);
        try {
            // 获取收货单基本信息
            Receipt receipt = receiptMapper.getReceiptById(id);

            if (receipt != null) {
                // 查询收货单明细
                List<ReceiptItem> items = receiptItemMapper.findByReceiptId(receipt.getId());
                receipt.setItems(items);
                log.info("获取到收货单明细, 数量: {}", items.size());
            }

            return receipt;
        } catch (Exception e) {
            log.error("根据ID获取收货单失败: {}", id, e);
            return null;
        }
    }

    @Override
    public List<Receipt> getReceiptsByOrderId(Long orderId) {
        log.info("根据订单ID获取关联收货单: {}", orderId);
        try {
            // 获取收货单基本信息
            List<Receipt> receipts = receiptMapper.getReceiptsByOrderId(orderId);

            // 为每个收货单加载明细数据
            if (receipts != null && !receipts.isEmpty()) {
                for (Receipt receipt : receipts) {
                    List<ReceiptItem> items = receiptItemMapper.findByReceiptId(receipt.getId());
                    receipt.setItems(items);
                }
                log.info("获取到订单[{}]关联的收货单: {}个, 已加载明细数据", orderId, receipts.size());
            }

            return receipts;
        } catch (Exception e) {
            log.error("根据订单ID获取关联收货单失败: {}", orderId, e);
            return List.of();
        }
    }

    @Override
    @Transactional
    public Receipt createReceipt(Receipt receipt) {
        log.info("创建收货单: {}", receipt);
        try {
            // 检查收货单号是否为自动生成
            if (receipt.getReceiptNumber() == null || receipt.getReceiptNumber().isEmpty()
                    || "系统自动生成".equals(receipt.getReceiptNumber())
                    || "自动生成".equals(receipt.getReceiptNumber())) {
                receipt.setReceiptNumber(generateReceiptNumber());
            }

            // 设置逻辑删除标记
            receipt.setDeleted((byte) 0);

            // 保存收货单基本信息
            receiptMapper.insertReceipt(receipt);

            log.info("收货单基本信息保存成功, ID: {}", receipt.getId());

            // 保存收货单明细
            if (receipt.getItems() != null && !receipt.getItems().isEmpty()) {
                log.info("开始保存收货单明细, 数量: {}", receipt.getItems().size());

                List<ReceiptItem> receiptItems = new ArrayList<>();
                for (ReceiptItem item : receipt.getItems()) {
                    // 设置关联的收货单ID
                    item.setReceiptId(receipt.getId());
                    receiptItems.add(item);
                }

                // 批量插入收货单明细
                if (!receiptItems.isEmpty()) {
                    int insertCount = receiptItemMapper.batchInsert(receiptItems);
                    log.info("收货单明细保存成功, 影响行数: {}", insertCount);
                }
            } else {
                log.warn("收货单没有明细项, 收货单ID: {}", receipt.getId());
            }

            // 如果关联了订单，可以考虑更新订单状态
            if (receipt.getOrderId() != null) {
                Order order = findOrderById(receipt.getOrderId());
                if (order != null && "待收货".equals(order.getStatus())) {
                    order.setStatus("已收货");
                    updateOrder(order);
                    log.info("更新订单状态为已收货, 订单ID: {}", receipt.getOrderId());
                }
            }

            return receipt;
        } catch (Exception e) {
            log.error("创建收货单失败", e);
            throw new RuntimeException("创建收货单失败: " + e.getMessage(), e);
        }
    }

    @Override
    @Transactional
    public Receipt updateReceipt(Long id, Receipt receipt) {
        log.info("更新收货单: {}, ID: {}", receipt, id);
        try {
            // 先获取原收货单信息，确认存在
            Receipt existingReceipt = receiptMapper.getReceiptById(id);
            if (existingReceipt == null) {
                log.error("收货单不存在, ID: {}", id);
                throw new RuntimeException("收货单不存在");
            }

            // 设置收货单ID，确保更新的是正确的记录
            receipt.setId(id);

            // 更新收货单基本信息
            receiptMapper.updateReceipt(receipt);
            log.info("收货单基本信息更新成功, ID: {}", id);

            // 处理明细项，如果有传递明细
            if (receipt.getItems() != null && !receipt.getItems().isEmpty()) {
                // 先删除旧的明细项
                receiptItemMapper.deleteByReceiptId(id);
                log.info("已删除收货单原有明细项, 收货单ID: {}", id);

                // 添加新的明细项
                List<ReceiptItem> items = receipt.getItems();
                for (ReceiptItem item : items) {
                    item.setReceiptId(id); // 确保明细项关联到正确的收货单
                }

                // 批量插入新明细项
                receiptItemMapper.batchInsert(items);
                log.info("成功添加{}个新明细项, 收货单ID: {}", items.size(), id);
            }

            // 重新获取完整的收货单信息，包括明细
            Receipt updatedReceipt = getReceiptById(id);
            return updatedReceipt;
        } catch (Exception e) {
            log.error("更新收货单失败: {}", id, e);
            throw new RuntimeException("更新收货单失败: " + e.getMessage(), e);
        }
    }

    @Override
    @Transactional
    public boolean deleteReceipt(Long id) {
        log.info("删除收货单: {}", id);
        try {
            return receiptMapper.deleteReceipt(id) > 0;
        } catch (Exception e) {
            log.error("删除收货单失败: {}", id, e);
            throw new RuntimeException("删除收货单失败", e);
        }
    }

    @Override
    @Transactional
    public boolean batchDeleteReceipt(List<Long> ids) {
        log.info("批量删除收货单: {}", ids);
        try {
            return receiptMapper.batchDeleteReceipt(ids) > 0;
        } catch (Exception e) {
            log.error("批量删除收货单失败: {}", ids, e);
            throw new RuntimeException("批量删除收货单失败", e);
        }
    }

    @Override
    @Transactional
    public Receipt acceptReceipt(Long id, String status) {
        log.info("收货单验收: {}, 状态: {}", id, status);
        try {
            Receipt receipt = receiptMapper.getReceiptById(id);
            if (receipt != null) {
                receipt.setStatus(status);
                receiptMapper.updateReceipt(receipt);
                return receipt;
            }
            return null;
        } catch (Exception e) {
            log.error("收货单验收失败: {}", id, e);
            throw new RuntimeException("收货单验收失败", e);
        }
    }

    @Override
    public Object getReceiptPage(int pageNum, int pageSize, String receiptNumber, String supplierName,
                                 String status, String startDate, String endDate, String receiptDate) {
        log.info("分页查询收货单: 页码={}, 每页数量={}, 收货单号={}, 供应商={}, 状态={}, 开始日期={}, 结束日期={}, 收货日期={}",
                pageNum, pageSize, receiptNumber, supplierName, status, startDate, endDate, receiptDate);
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("pageNum", pageNum);
            params.put("pageSize", pageSize);
            params.put("receiptNumber", receiptNumber);
            params.put("supplierName", supplierName);
            params.put("status", status);

            // 只有当日期不为null且不为空字符串时才添加到参数中
            if (startDate != null && !startDate.isEmpty()) {
                params.put("startDate", startDate);
            }
            if (endDate != null && !endDate.isEmpty()) {
                params.put("endDate", endDate);
            }
            if (receiptDate != null && !receiptDate.isEmpty()) {
                params.put("receiptDate", receiptDate);
            }

            // 计算分页偏移量
            int offset = (pageNum - 1) * pageSize;
            params.put("offset", offset);

            long total = receiptMapper.countReceipts(params);
            List<Receipt> list = receiptMapper.getReceiptPage(params);

            Map<String, Object> result = new HashMap<>();
            result.put("total", total);
            result.put("list", list);
            return result;
        } catch (Exception e) {
            log.error("分页查询收货单失败", e);
            return Map.of("total", 0, "list", List.of());
        }
    }

    @Override
    public ReceiptStatistics getReceiptStatusStatistics() {
        log.info("获取收货单状态统计");
        try {
            // 查询各状态的收货单数量
            List<Map<String, Object>> statusStats = receiptMapper.countByStatus();

            // 创建统计对象
            ReceiptStatistics statistics = new ReceiptStatistics();

            // 初始化默认值
            statistics.setPendingCount(0);
            statistics.setAcceptedCount(0);
            statistics.setTotalCount(0);

            // 填充统计数据
            for (Map<String, Object> stat : statusStats) {
                String status = (String) stat.get("status");
                int count = ((Number) stat.get("count")).intValue();

                if ("待验收".equals(status)) {
                    statistics.setPendingCount(count);
                } else if ("已验收".equals(status)) {
                    statistics.setAcceptedCount(count);
                }

                // 累加总数
                statistics.setTotalCount(statistics.getTotalCount() + count);
            }

            // 查询总金额
            BigDecimal totalAmount = receiptMapper.sumTotalAmount();
            statistics.setTotalAmount(totalAmount);

            return statistics;
        } catch (Exception e) {
            log.error("获取收货单状态统计失败", e);
            return new ReceiptStatistics();
        }
    }

    @Override
    public byte[] exportReceipts(String receiptNumber, String supplierName, String status, String startDate, String endDate) {
        log.info("导出收货单数据，条件：收货单号={}, 供应商={}, 状态={}, 开始日期={}, 结束日期={}",
                receiptNumber, supplierName, status, startDate, endDate);

        // 构建查询参数
        Map<String, Object> params = new HashMap<>();
        // 只有在参数非空且有值时才添加到查询条件中
        if (receiptNumber != null && !receiptNumber.trim().isEmpty()) {
            params.put("receiptNumber", receiptNumber);
        }
        if (supplierName != null && !supplierName.trim().isEmpty()) {
            params.put("supplierName", supplierName);
        }
        if (status != null && !status.trim().isEmpty()) {
            params.put("status", status);
        }
        if (startDate != null && !startDate.trim().isEmpty()) {
            params.put("startDate", startDate);
        }
        if (endDate != null && !endDate.trim().isEmpty()) {
            params.put("endDate", endDate);
        }

        // 查询收货单数据 - 没有条件时会查询所有收货单
        List<Receipt> receipts = receiptMapper.getReceiptsByParams(params);
        log.info("查询到 {} 条符合条件的收货单数据", receipts.size());

        // 导出Excel
        try {
            // 创建工作簿
            Workbook workbook = new XSSFWorkbook();
            Sheet sheet = workbook.createSheet("收货单数据");

            // 创建表头
            Row headerRow = sheet.createRow(0);
            String[] headers = {"收货单编号", "订单编号", "供应商", "收货日期", "收货金额", "状态", "创建时间"};
            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
            }

            // 填充数据
            int rowNum = 1;

            // 添加日期格式化器
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

            for (Receipt receipt : receipts) {
                Row row = sheet.createRow(rowNum++);
                row.createCell(0).setCellValue(receipt.getReceiptNumber());
                row.createCell(1).setCellValue(receipt.getOrderNumber());
                row.createCell(2).setCellValue(receipt.getSupplierName());

                // 使用格式化器格式化收货日期
                if (receipt.getReceiptDate() != null) {
                    row.createCell(3).setCellValue(receipt.getReceiptDate().format(dateFormatter));
                } else {
                    row.createCell(3).setCellValue("");
                }

                row.createCell(4).setCellValue(receipt.getTotalAmount() != null ? receipt.getTotalAmount().doubleValue() : 0);
                row.createCell(5).setCellValue(receipt.getStatus());
                row.createCell(6).setCellValue(receipt.getCreateTime() != null ? receipt.getCreateTime().toString() : "");
            }

            // 调整列宽
            for (int i = 0; i < headers.length; i++) {
                sheet.autoSizeColumn(i);
            }

            // 转换为字节数组
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            workbook.write(outputStream);
            workbook.close();

            byte[] fileContent = outputStream.toByteArray();
            log.info("成功生成Excel文件，大小: {} 字节", fileContent.length);
            return fileContent;
        } catch (IOException e) {
            log.error("导出收货单Excel出错", e);
            throw new RuntimeException("导出收货单失败", e);
        }
    }

    @Override
    public BigDecimal getTotalReceiptAmount() {
        log.info("获取收货单总金额");
        try {
            return receiptMapper.getTotalReceiptAmount();
        } catch (Exception e) {
            log.error("获取收货单总金额失败", e);
            return BigDecimal.ZERO;
        }
    }

    @Override
    public List<Map<String, Object>> getReceiptStatsBySupplier(int limit) {
        log.info("获取按供应商统计的收货单数据, limit: {}", limit);
        try {
            return receiptMapper.getReceiptStatsBySupplier(limit);
        } catch (Exception e) {
            log.error("获取按供应商统计的收货单数据失败", e);
            return List.of();
        }
    }

//    @Override
//    public List<Map<String, Object>> sumAmountGroupByMonth(LocalDate startDate, LocalDate endDate) {
//        return receiptMapper.sumAmountGroupByMonth(startDate, endDate);
//    }

    @Override
    public int getCurrentMonthReceiptCount() {
        log.info("获取当月收货单数量");
        try {
            return receiptMapper.countByCurrentMonth();
        } catch (Exception e) {
            log.error("获取当月收货单数量失败", e);
            return 0;
        }
    }

    @Override
    public BigDecimal getCurrentMonthReceiptAmount() {
        log.info("获取当月收货单金额");
        try {
            return receiptMapper.sumAmountByCurrentMonth();
        } catch (Exception e) {
            log.error("获取当月收货单金额失败", e);
            return BigDecimal.ZERO;
        }
    }

    @Override
    public List<Map<String, Object>> getMonthlyReceiptTrend(int year) {
        log.info("获取{}年月度收货单趋势数据", year);
        try {
            // 获取指定年份的月度趋势数据
            log.info("开始查询{}年的月度收货单趋势数据", year);
            List<Map<String, Object>> monthlyData = receiptMapper.getMonthlyTrend(year);

            // 记录原始数据
            if (monthlyData != null && !monthlyData.isEmpty()) {
                log.info("从数据库获取到的原始月度趋势数据: {}, 共{}条记录", monthlyData, monthlyData.size());
                for (int i = 0; i < monthlyData.size(); i++) {
                    Map<String, Object> item = monthlyData.get(i);
                    log.info("第{}条数据: month={}, month_str={}, count={}, totalAmount={}, 类型: month={}, month_str={}, count={}, totalAmount={}",
                            i + 1,
                            item.get("month"),
                            item.get("month_str"),
                            item.get("count"),
                            item.get("totalAmount"),
                            item.get("month") != null ? item.get("month").getClass().getName() : "null",
                            item.get("month_str") != null ? item.get("month_str").getClass().getName() : "null",
                            item.get("count") != null ? item.get("count").getClass().getName() : "null",
                            item.get("totalAmount") != null ? item.get("totalAmount").getClass().getName() : "null");
                }
            } else {
                log.warn("数据库中没有找到{}年的月度收货单趋势数据", year);
                monthlyData = new ArrayList<>();
            }

            // 确保结果包含1-12月的数据，如果某月没有数据则填充0
            Map<String, Map<String, Object>> monthDataMap = new HashMap<>();
            for (Map<String, Object> data : monthlyData) {
                String monthStr = (String) data.get("month_str");
                log.debug("处理月份数据: {}", monthStr);
                monthDataMap.put(monthStr, data);
            }

            List<Map<String, Object>> result = new ArrayList<>();
            for (int i = 1; i <= 12; i++) {
                String monthKey = String.format("%d-%02d", year, i);
                log.debug("处理月份: {}", monthKey);
                if (monthDataMap.containsKey(monthKey)) {
                    log.debug("月份{}存在数据，使用 数据", monthKey);
                    Map<String, Object> monthData = monthDataMap.get(monthKey);
                    // 创建新的Map，只保留前端需要的字段
                    Map<String, Object> resultData = new HashMap<>();
                    resultData.put("month", monthKey);
                    resultData.put("count", monthData.get("count"));
                    resultData.put("totalAmount", monthData.get("totalAmount"));
                    result.add(resultData);
                } else {
                    log.debug("月份{}没有数据，使用默认数据", monthKey);
                    // 如果该月没有数据，则创建默认数据
                    Map<String, Object> defaultData = new HashMap<>();
                    defaultData.put("month", monthKey);
                    defaultData.put("count", 0);
                    defaultData.put("totalAmount", BigDecimal.ZERO);
                    result.add(defaultData);
                }
            }

            // 记录最终返回的数据
            log.info("最终返回的月度趋势数据: {}, 共{}条记录", result, result.size());

            return result;
        } catch (Exception e) {
            log.error("获取{}年月度收货单趋势数据失败: {}", year, e.getMessage(), e);

            // 创建一个默认的空数据集合
            List<Map<String, Object>> defaultResult = new ArrayList<>();
            for (int i = 1; i <= 12; i++) {
                Map<String, Object> defaultData = new HashMap<>();
                defaultData.put("month", String.format("%d-%02d", year, i));
                defaultData.put("count", 0);
                defaultData.put("totalAmount", BigDecimal.ZERO);
                defaultResult.add(defaultData);
            }

            log.info("由于错误，返回默认的空数据集合，共{}条记录", defaultResult.size());
            return defaultResult;
        }
    }

    @Override
    public List<Receipt> findBySupplierAndAmount(String supplierName, BigDecimal targetAmount,
                                                 BigDecimal minAmount, BigDecimal maxAmount) {
        return receiptMapper.findBySupplierAndAmount(supplierName, minAmount, maxAmount);
    }

    @Override
    public List<Receipt> findBySimilarSupplierAndAmount(String supplierName, BigDecimal targetAmount,
                                                        BigDecimal minAmount, BigDecimal maxAmount) {
        log.info("根据近似供应商名称和金额范围查询收货单: 供应商={}, 目标金额={}, 范围={}-{}",
                supplierName, targetAmount, minAmount, maxAmount);
        try {
            return receiptMapper.findBySimilarSupplierAndAmount(supplierName, minAmount, maxAmount);
        } catch (Exception e) {
            log.error("根据近似供应商名称和金额范围查询收货单失败", e);
            return List.of();
        }
    }

    @Override
    public Receipt findByReceiptNumber(String receiptNumber) {
        log.info("根据收货单号查询收货单: {}", receiptNumber);
        if (receiptNumber == null || receiptNumber.trim().isEmpty()) {
            return null;
        }

        try {
            // 使用条件查询收货单
            Map<String, Object> params = new HashMap<>();
            params.put("receiptNumber", receiptNumber);
            List<Receipt> receipts = receiptMapper.getReceiptsByParams(params);

            // 如果找到收货单，加载收货单明细
            if (receipts != null && !receipts.isEmpty()) {
                Receipt receipt = receipts.get(0);
                List<ReceiptItem> items = receiptItemMapper.findByReceiptId(receipt.getId());
                receipt.setItems(items);
                return receipt;
            }

            return null;
        } catch (Exception e) {
            log.error("根据收货单号查询收货单失败: {}", receiptNumber, e);
            return null;
        }
    }

    @Override
    public List<Receipt> findByOrderNumber(String orderNumber) {
        log.info("根据订单编号查询收货单: {}", orderNumber);
        if (orderNumber == null || orderNumber.trim().isEmpty()) {
            return List.of();
        }

        try {
            // 使用订单编号查询收货单
            List<Receipt> receipts = receiptMapper.findByOrderNumber(orderNumber);

            // 加载收货单明细
            if (receipts != null && !receipts.isEmpty()) {
                for (Receipt receipt : receipts) {
                    List<ReceiptItem> items = receiptItemMapper.findByReceiptId(receipt.getId());
                    receipt.setItems(items);
                }
            }

            return receipts != null ? receipts : List.of();
        } catch (Exception e) {
            log.error("根据订单编号查询收货单失败: {}", orderNumber, e);
            return List.of();
        }
    }

    /**
     * 生成收货单号
     * 格式：GR + 年月日 + 四位序号
     * 例如：GR2023052300001
     */
    private String generateReceiptNumber() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateStr = sdf.format(new Date());
        int randomNum = ThreadLocalRandom.current().nextInt(1000, 10000);
        return "GR" + dateStr + String.format("%04d", randomNum);
    }

    /**
     * 查询订单信息（ 项目中应该调用订单服务）
     *
     * @param orderId 订单ID
     * @return 订单信息
     */
    private Order findOrderById(Long orderId) {
        try {
            return orderMapper.selectById(orderId);
        } catch (Exception e) {
            log.error("查询订单信息失败, 订单ID: {}", orderId, e);
            return null;
        }
    }

    /**
     * 查询订单明细（ 项目中应该调用订单服务）
     *
     * @param orderId 订单ID
     * @return 订单明细列表
     */

    /**
     * 更新订单信息（ 项目中应该调用订单服务）
     *
     * @param order 订单信息
     */
    private void updateOrder(Order order) {
        try {
            orderMapper.updateById(order);
        } catch (Exception e) {
            log.error("更新订单状态失败, 订单ID: {}", order.getId(), e);
            throw new BusinessException("更新订单状态失败: " + e.getMessage());
        }
    }
} 